package com.example.sample.logic;

import java.util.ArrayList;
import java.util.List;

import android.content.ContentProvider;
import android.content.ContentProviderOperation;
import android.content.ContentProviderResult;
import android.content.ContentValues;
import android.content.Context;
import android.content.OperationApplicationException;
import android.content.UriMatcher;
import android.database.Cursor;
import android.database.sqlite.SQLiteDatabase;
import android.database.sqlite.SQLiteOpenHelper;
import android.net.Uri;
import android.util.Log;
import android.util.SparseArray;

import com.example.sample.SampleApp;

import net.liteheaven.xblib.common.ui.ToastUtil;

/**
 *
 * ContentProvider演示类，同时演示sqllite的用法
 *
 * @author  LiangYu
 * @data:  2015-1-5 下午6:22:55
 * @version:  V1.0
 */
public class ChatMessageProvider extends ContentProvider {

    // UriMatcher匹配代码
    public static final int MATHER_CODE_RIVER = 1;

    public static class River {
        public River(String name, int len) {
            this.name = name;
            this.len = len;
        }

        public String name;
        public int len;
    }

    public static final String ID = "_id";
    public static final String NAME = "name";
    public static final String CONTENT = "content";
    public static final String PREFIX = "content://";
    // 表名不能携带数字
    public static final String DATABASE_NAME = "river_db";
    public static final String TABLE_NAME = "rivers_europe";
    public static final String AUTHORITY = "com.example.provider.world_river";
    public static final Uri CONTENT_URI = Uri.parse(PREFIX + AUTHORITY + "/" + TABLE_NAME);

    // Defines a helper object that matches content URIs to table-specific parameters
    private static final UriMatcher sUriMatcher;

    // Stores the MIME types served by this provider
    private static final SparseArray<String> sMimeTypes;

    private static DBOpenHelper mHelper;

    private static final int DB_VER = 1;

    private static final List<River> RIVERS = new ArrayList<River>();

    static {
        River river = new River("尼罗河", 6380);
        RIVERS.add(river);
        river = new River("红河", 111);
        RIVERS.add(river);
        river = new River("多瑙河", 111);
        RIVERS.add(river);
        river = new River("莱茵河", 111);
        RIVERS.add(river);

        // Creates an object that associates content URIs with numeric codes
        sUriMatcher = new UriMatcher(0);

        /*
         * Sets up an array that maps content URIs to MIME types, via a mapping between the
         * URIs and an integer code. These are custom MIME types that apply to tables and rows
         * in this particular provider.
         */
        sMimeTypes = new SparseArray<String>();

        // 为table绑定code
        sUriMatcher.addURI(AUTHORITY, TABLE_NAME + "/*" , MATHER_CODE_RIVER);

        // 为code绑定MIME
        sMimeTypes.put(MATHER_CODE_RIVER, "vnd.android.cursor.dir/vnd." + AUTHORITY + "." + TABLE_NAME);
    }

    @Override
    public int delete(Uri uri, String selection, String[] selectionArgs) {
        int code = sUriMatcher.match(uri);
        switch (code) {
            case MATHER_CODE_RIVER:
                String dbName = getTableName(uri);
                SQLiteDatabase localSQLiteDatabase = mHelper.getWritableDatabase();
                int affected = localSQLiteDatabase.delete(dbName, selection, selectionArgs);
                if (affected > 0){
                    getContext().getContentResolver().notifyChange(uri, null);
                }
                return affected;
        }
        return 0;
    }

    @Override
    public String getType(Uri uri) {
        return sMimeTypes.get(sUriMatcher.match(uri));
    }

    @Override
    public Uri insert(Uri uri, ContentValues values) {
        int code = sUriMatcher.match(uri);
        switch (code){
            case MATHER_CODE_RIVER:
                String dbName = getTableName(uri);
                // Creates a writeable database or gets one from cache
                SQLiteDatabase localSQLiteDatabase = mHelper.getWritableDatabase();

                // Inserts the row into the table and returns the new row's _id value
                long id = localSQLiteDatabase.insert(
                        dbName,
                        null,
                        values
                );

                // If the insert succeeded, notify a change and return the new row's content URI.
                if (-1 != id) {
                    getContext().getContentResolver().notifyChange(uri, null);
                    return Uri.withAppendedPath(uri, Long.toString(id));
                } else {
                    ToastUtil.show(SampleApp.getApp(), "插入失败");
                }
        }
        return null;
    }

    @Override
    public boolean onCreate() {
        mHelper = new DBOpenHelper(getContext());
        boolean result = mHelper != null;
        return result;
    }

    @Override
    public Cursor query(Uri uri, String[] projection, String selection,
                        String[] selectionArgs, String sortOrder) {
        switch (sUriMatcher.match(uri)) {
            case MATHER_CODE_RIVER:
                String dbName = getTableName(uri);
                SQLiteDatabase database = mHelper.getReadableDatabase();
                Cursor cursor = database.query(dbName, projection,
                        selection, selectionArgs, null, null, sortOrder);
                //设置NotificationUri
                cursor.setNotificationUri(getContext().getContentResolver(), uri);
                return cursor;
        }
        return null;
    }

    @Override
    public int update(Uri uri, ContentValues values, String selection,
                      String[] selectionArgs) {
        switch (sUriMatcher.match(uri)){
            case MATHER_CODE_RIVER:
                String dbName = getTableName(uri);
                // Creats a new writeable database or retrieves a cached one
                SQLiteDatabase localSQLiteDatabase = mHelper.getWritableDatabase();

                // Updates the table
                int rows = localSQLiteDatabase.update(
                        dbName,
                        values,
                        selection,
                        selectionArgs);

                // If the update succeeded, notify a change and return the number of updated rows.
                if (0 != rows) {
                    getContext().getContentResolver().notifyChange(uri, null);
                    return rows;
                }
        }
        return 0;
    }

    @Override
    public ContentProviderResult[] applyBatch(ArrayList<ContentProviderOperation> operations)
            throws OperationApplicationException {
        SQLiteDatabase db = mHelper.getWritableDatabase();
        db.beginTransaction();
        try{
            ContentProviderResult[]results = super.applyBatch(operations);
            db.setTransactionSuccessful();
            return results;
        }finally {
            db.endTransaction();
        }
    }

    private class DBOpenHelper extends SQLiteOpenHelper {
        /**
         * Instantiates a new SQLite database using the supplied database name and version
         *
         * @param context The current context
         */
        DBOpenHelper(Context context) {
            super(context, DATABASE_NAME, null, DB_VER);
        }


        /**
         * Executes the queries to drop all of the tables from the database.
         *
         * @param db A handleEvt to the provider's backing database.
         */
        private void dropTables(SQLiteDatabase db) {

        }

        /**
         * Does setup of the database. The system automatically invokes this method when
         * SQLiteDatabase.getWriteableDatabase() or SQLiteDatabase.getReadableDatabase() are
         * invoked and no db instance is available.
         *
         * @param db the database instance in which to create the tables.
         */
        @Override
        public void onCreate(SQLiteDatabase db) {
        }

        /**
         * Handles upgrading the database from a previous version. Drops the old tables and creates
         * new ones.
         *
         * @param db The database to upgrade
         * @param version1 The old database version
         * @param version2 The new database version
         */
        @Override
        public void onUpgrade(SQLiteDatabase db, int version1, int version2) {
            Log.w(DBOpenHelper.class.getName(),
                    "Upgrading database from version " + version1 + " to "
                            + version2 + ", which will destroy all the existing data");

            // Drops all the existing tables in the database
            dropTables(db);

            // Invokes the onCreate callback to build new tables
            onCreate(db);
        }
        /**
         * Handles downgrading the database from a new to a previous version. Drops the old tables
         * and creates new ones.
         * @param db The database object to downgrade
         * @param version1 The old database version
         * @param version2 The new database version
         */
        @Override
        public void onDowngrade(SQLiteDatabase db, int version1, int version2) {
            Log.w(DBOpenHelper.class.getName(),
                    "Downgrading database from version " + version1 + " to "
                            + version2 + ", which will destroy all the existing data");

            // Drops all the existing tables in the database
            dropTables(db);

            // Invokes the onCreate callback to build new tables
            onCreate(db);
        }
    }

    private static String getTableName(Uri uri){
        return "session" + uri.getPathSegments().get(1);
    }

    public static void createTable(Uri uri){
        String tableName = getTableName(uri);
        String sqlStr = "create table " + "if not exists " + tableName
                + "( " + ID + " integer primary key autoincrement," + NAME + " text,"
                + CONTENT + " text" + ");";
        SQLiteDatabase db = mHelper.getWritableDatabase();
        try {
            db.execSQL(sqlStr);
        }catch (Exception e){
            e.printStackTrace();
        }
    }

    public static Uri getTableUri(long sessionId){
        return Uri.withAppendedPath(CONTENT_URI, ""+sessionId);
    }
}